package firear.remoteinput;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Looper;
import android.util.Log;
import android.widget.ImageView;
import android.widget.Toast;

import org.nanohttpd.protocols.http.NanoHTTPD;

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

public class RemoteInput {
    private static final String TAG = "RemoteInput";
    private WeakReference<Context> mCtx = null;
    private boolean mServerStarted = false;
    private String mUrl = "";
    private Looper mDialogLooper = null;
    private Dialog mDialog = null;

    public static RemoteInput getInstance() {
        return SingleTonHoler.INSTANCE;
    }

    public void setContext(Context ctx) {
        mCtx = new WeakReference<Context>(ctx);
    }

    private void startWebServer(WebSocketCallback cb) {
        Context ctx = mCtx.get();
        int port = 8000;
        String targetPath = ctx.getFilesDir() + "/webroot";
        String cors = "*";
        NanoHTTPD server = new WebServer("0.0.0.0", port, new File(targetPath), false, cors, new WebSocketCallback() {
            @Override
            public void onStartFailed(String error) {
                cb.onStartFailed(error);

            }

            @Override
            public void onStartSucceed(String info) {
                cb.onStartSucceed(info);
            }

            @Override
            public void onClientConnected() {
                cb.onClientConnected();
                dismissQrcode();
            }

            @Override
            public void onClientDisconnected() {
                cb.onClientDisconnected();
            }

            @Override
            public void onMessageReceived(String type, String data) {
                cb.onMessageReceived(type, data);
            }
        });
        try {
            server.start(60000);
            mUrl = String.format("http://%s:%d", getLocalIp(), port);
            Log.i(TAG, mUrl);
            mServerStarted = true;
        } catch (IOException ioe) {
            System.err.println("Couldn't start server:\n" + ioe);
            System.exit(-1);
        }
        Log.i(TAG, "run start");
    }

    public void start(boolean showqrcode, WebSocketCallback cb) {
        Log.i(TAG, "start");
        releaseWebRoot();
        if (!mServerStarted) {
            startWebServer(cb);
        }
        Toast.makeText(mCtx.get(), mUrl, Toast.LENGTH_SHORT).show();
        if(showqrcode){
            new Thread(() -> {
                Looper.prepare();
                mDialogLooper = Looper.myLooper();
                showQrcode(mUrl);
                Looper.loop();
                Log.i(TAG, "loop end");
            }).start();
        }
    }

    private void dismissQrcode() {
        if (mDialog != null) {
            mDialog.dismiss();
        }
    }

    public void stop() {

    }

    private void showQrcode(String txt) {
        Context ctx = mCtx.get();
        Bitmap pic = QRCodeUtil.createQRCodeBitmap(txt, 500, 500);
        ImageView img = new ImageView(ctx);
        img.setImageBitmap(pic);
        AlertDialog.Builder b = new AlertDialog.Builder(ctx);
        b.setView(img);
        mDialog = b.show();
        mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialogInterface) {
                Log.i(TAG, "onDismiss");
                mDialogLooper.quit();
            }
        });
    }

    private String getLocalIp() {
        //取 Wifi IP的方法
        Context app = mCtx.get();
        WifiManager wifiManager = (WifiManager) app.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (wifiManager.isWifiEnabled()
                && wifiManager.getWifiState() == wifiManager.WIFI_STATE_ENABLED) {
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            if (wifiInfo != null) {
                int ipAddress = wifiInfo.getIpAddress();
                if (ipAddress == 0)
                    return "";
                return ((ipAddress & 0xff) + "." + (ipAddress >> 8 & 0xff)
                        + "." + (ipAddress >> 16 & 0xff) + "." + (ipAddress >> 24 & 0xff));
            }
        } else {
            try {
                for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                    NetworkInterface intf = en.nextElement();
                    for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                        InetAddress inetAddress = enumIpAddr.nextElement();
                        if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress()) {
                            return inetAddress.getHostAddress();
                        }
                    }
                }
            } catch (SocketException ex) {
                ex.printStackTrace();
            }
        }
        return "";
    }

    private void releaseWebRoot() {
        Context ctx = mCtx.get();
        String targetPath = ctx.getFilesDir() + "/webroot";
        if (!new File(targetPath).exists()) {
            AssetsUtils.copyAssets(ctx, "webroot", targetPath);
        }
    }

    private static class SingleTonHoler {
        private static final RemoteInput INSTANCE = new RemoteInput();
    }

}
